package com.mstore.action;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;

import com.alipay.config.AlipayConfig;
import com.alipay.util.AlipayNotify;
import com.alipay.util.AlipaySubmit;
import com.mstore.config.Constants;
import com.mstore.interceptor.Authority;
import com.mstore.pojo.Account;
import com.mstore.pojo.AccountAlipayGoods;
import com.mstore.pojo.AlipayAccount;
import com.mstore.pojo.OrderInfo;
import com.mstore.pojo.TradeInfo;
import com.mstore.service.AccountAlipayGoodsService;
import com.mstore.service.AccountService;
import com.mstore.service.AlipayAccountService;
import com.mstore.service.OrderInfoService;
import com.mstore.service.TradeInfoService;
import com.opensymphony.xwork2.ActionContext;

public class TradeInfoAction extends BaseAction implements SessionAware,
		ServletRequestAware, ServletResponseAware {

	private static final long serialVersionUID = -6793952569026846326L;

	private TradeInfoService tradeInfoService;

	private OrderInfoService orderInfoService;

	private AccountService accountService;

	private String result;

	private Map<String, Object> session;

	private TradeInfo tradeInfo;

	private OrderInfo orderInfo;

	private AlipayAccount alipayAccount;

	private String backMessage;

	private static Logger logger = Logger.getLogger(TradeInfoAction.class
			.getName());

	private AlipayAccountService alipayAccountService;

	private HttpServletResponse response;

	private HttpServletRequest request;

	private AccountAlipayGoodsService accountAlipayGoodsService;

	/**
	 * 跳转到支付页面
	 */
	public String initAlipayToBalance() {
		return "toAlipayToBalance";
	}

	/**
	 * 用支付宝充值
	 */
	public String useAlipayToBalance() {
		// 调用支付宝支付API，获取用户充值金额
		float alipayAmount = 0f;

		// 更新企业表实时余额、累计充值
		try {
			Account ac = (Account) session.get("account");
			ac.setRbalance(alipayAmount);
			ac.setTotalDeposits(ac.getTotalDeposits() + alipayAmount);
			accountService.updateAccount(ac);
		}
		catch (Exception e) {
			logger.error("session为空", e);
			result = ERROR_TIP;
			return "error";
		}

		backMessage = "1";
		return "useAlipayToBalanceSuccess";
	}

	/**
	 * 用支付宝购买
	 */
	public String useAlipayToPay() {
		if (orderInfo == null) {
			result = "系统数据异常";
			return "error";
		}
		if (orderInfo.getOrderId() == null) {
			result = "系统数据异常";
			return "error";
		}

		orderInfo = orderInfoService.finadMyOrderInfoByOrderId(orderInfo
				.getOrderId());

		if (orderInfo == null) {
			result = "订单不存在";
			return "error";
		}

		// 调用支付宝API
		alipayAPI();

		ActionContext.getContext().getActionInvocation().getProxy()
				.setExecuteResult(false);

		return NONE;
	}

	/**
	 * 支付宝回调方法 生成交易流水账 更新订单信息
	 */
	@Authority(actionName = "maccount", privilege = "pass")
	public String addMyTradeInfo() {
		// 获取支付宝POST过来反馈信息
		Map<String, String> params = new HashMap<String, String>();
		@SuppressWarnings("rawtypes")
		Map requestParams = request.getParameterMap();
		for (@SuppressWarnings("rawtypes")
		Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i]
						: valueStr + values[i] + ",";
			}
			// 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
			params.put(name, valueStr);
		}

		// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
		// 商户订单号
		String out_trade_no = "";
		// 支付宝交易号
		// String trade_no = "";
		// 交易状态
		String trade_status = "";
		try {
			out_trade_no = new String(request.getParameter("out_trade_no")
					.getBytes("ISO-8859-1"), "UTF-8");
			// trade_no = new String(request.getParameter("trade_no").getBytes(
			// "ISO-8859-1"), "UTF-8");
			// TRADE_SUCCESS 交易成功
			trade_status = new String(request.getParameter("trade_status")
					.getBytes("ISO-8859-1"), "UTF-8");
		}
		catch (UnsupportedEncodingException e) {
			logger.error("支付宝回调方法addMyTradeInfo报错", e);
		}

		try {
			PrintWriter out = response.getWriter();

			if (AlipayNotify.verify(params)) {// 验证成功
				logger.info("支付宝回调方法addMyTradeInfo验证成功");
				// ////////////////////////////////////////////////////////////////////////////////////////
				// 请在这里加上商户的业务逻辑程序代码

				// ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——

				if (trade_status.equals("TRADE_FINISHED")) {
					// 判断该笔订单是否在商户网站中已经做过处理
					// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
					// 如果有做过处理，不执行商户的业务程序

					// 注意：
					// 该种交易状态只在两种情况下出现
					// 1、开通了普通即时到账，买家付款成功后。
					// 2、开通了高级即时到账，从该笔交易成功时间算起，过了签约时的可退款时限（如：三个月以内可退款、一年以内可退款等）后。
				}
				else if (trade_status.equals("TRADE_SUCCESS")) {
					// 判断该笔订单是否在商户网站中已经做过处理
					// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
					// 如果有做过处理，不执行商户的业务程序

					// 注意：
					// 该种交易状态只在一种情况下出现——开通了高级即时到账，买家付款成功后。

					logger.info("支付宝回传订单号: " + out_trade_no);
					OrderInfo myOrderInfo = orderInfoService
							.finadMyOrderInfoByOrderId(out_trade_no);

					if (myOrderInfo == null) {
						logger.error("支付宝回调方法addMyTradeInfo报错:订单不存在");
						out.println("fail");
						ActionContext.getContext().getActionInvocation()
								.getProxy().setExecuteResult(false);
						return NONE;
					}

					String price = "";
					if (params.get("price") != null) {
						price = params.get("price");
					}

					float fee = myOrderInfo.getTradeAmount();
					float priceToFee = Float.valueOf(price).floatValue();
					// 判断交易金额是否被篡改
					if (fee != priceToFee) {
						logger.error("支付宝回调方法addMyTradeInfo报错:订单价格被篡改！");
						out.println("fail");
						ActionContext.getContext().getActionInvocation()
								.getProxy().setExecuteResult(false);
						return NONE;
					}

					Account account = myOrderInfo.getAccount();
					Long eaId = account.getId();
					Long goodId = myOrderInfo.getGoods().getGoodsId();
					String goodType = myOrderInfo.getGoods().getGoodsType();

					tradeInfo = new TradeInfo();
					tradeInfo.setAccount(account);
					// 充值方式id或者订单id
					tradeInfo.setTradeId(myOrderInfo.getOrderId());
					// 交易类型 0支付 1充值
					// 此处为支付
					tradeInfo.setTradeType(0);
					// 交易金额
					// 此处应该要根据支付宝返回参数判断
					tradeInfo.setTradeAmount(priceToFee);

					// 买家付款时间
					String gmtPayment = "";
					if (params.get("gmt_payment") != null) {
						gmtPayment = params.get("gmt_payment");
					}

					logger.info("交易成功时间: " + gmtPayment);

					if (StringUtils.isBlank(gmtPayment)) {
						gmtPayment = getCreateTime();
					}
					tradeInfo.setTradeDate(gmtPayment);

					// 状态 0成功 1未完成 2失败
					tradeInfo.setStatus(0);
					// 生成交易流水账
					tradeInfoService.addMyTradeInfo(tradeInfo);

					// 更改订单状态
					myOrderInfo.setStatus(1); // 已支付
					orderInfoService.updateMyOrderInfo(myOrderInfo);

					// 将企业与订单绑定
					AccountAlipayGoods accountAlipayGood = accountAlipayGoodsService
							.getAccountAlipayGoodsByEaIdAndGoodtype(eaId,
									goodType);
					if (accountAlipayGood == null) {
						// 订单生效，与企业绑定
						accountAlipayGood = new AccountAlipayGoods();
						if (myOrderInfo.getTariff().getValidDays() == 0) {
							// 计数商品
							accountAlipayGood.setEaId(eaId);
							accountAlipayGood.setGoodType(goodType);
							accountAlipayGood.setGoodId(goodId);
							accountAlipayGood
									.setAmount(myOrderInfo.getAmount());

							accountAlipayGoodsService
									.addAccountAlipayGoods(accountAlipayGood);
						}
					}
					else {
						// 更新企业使用该订单对应商品的权限
						if (myOrderInfo.getTariff().getValidDays() == 0) {
							// 计数商品
							accountAlipayGood.setAmount(accountAlipayGood
									.getAmount() + myOrderInfo.getAmount());
							accountAlipayGoodsService
									.updateAccountAlipayGoods(accountAlipayGood);
						}
					}
				}

				out.println("success"); // 请不要修改或删除

				// ////////////////////////////////////////////////////////////////////////////////////////
			}
			else {// 验证失败
				out.println("fail");
			}
		}
		catch (IOException e) {
			logger.error("支付宝回调方法addMyTradeInfo报错", e);
		}

		ActionContext.getContext().getActionInvocation().getProxy()
				.setExecuteResult(false);

		return NONE;
	}

	/**
	 * 组装支付宝支付参数
	 */
	private void alipayAPI() {
		// 支付类型
		String payment_type = "1";
		// 必填，不能修改
		// 服务器异步通知页面路径
		String notify_url = Constants.alipayGateway
				+ "/tradeinfoaction!addMyTradeInfo";
		// 需http://格式的完整路径，不能加?id=123这类自定义参数 //页面跳转同步通知页面路径
		String return_url = "";
		// 需http://格式的完整路径，不能加?id=123这类自定义参数，不能写成http://localhost/ //卖家支付宝帐户
		String seller_email = Constants.alipayAccount;
		// 必填 //商户订单号
		String out_trade_no = orderInfo.getOrderId();
		// 商户网站订单系统中唯一订单号，必填 //订单名称
		String subject = orderInfo.getGoodsName();
		// 必填 //付款金额
		String total_fee = "" + orderInfo.getTariff().getFee();
		// 必填 //订单描述
		String body = orderInfo.getDescription();
		// 商品展示地址
		String show_url = "";
		String anti_phishing_key = "";
		// 若要使用请调用类文件submit中的query_timestamp函数 //客户端的IP地址
		String exter_invoke_ip = "";
		// 非局域网的外网IP地址，如：221.0.0.1

		// 把请求参数打包成数组
		Map<String, String> sParaTemp = new HashMap<String, String>();
		sParaTemp.put("service", "create_direct_pay_by_user");
		sParaTemp.put("partner", AlipayConfig.partner);
		sParaTemp.put("_input_charset", AlipayConfig.input_charset);
		sParaTemp.put("payment_type", payment_type);
		sParaTemp.put("notify_url", notify_url);
		sParaTemp.put("return_url", return_url);
		sParaTemp.put("seller_email", seller_email);
		sParaTemp.put("out_trade_no", out_trade_no);
		sParaTemp.put("subject", subject);
		sParaTemp.put("total_fee", total_fee);
		sParaTemp.put("body", body);
		sParaTemp.put("show_url", show_url);
		sParaTemp.put("anti_phishing_key", anti_phishing_key);
		sParaTemp.put("exter_invoke_ip", exter_invoke_ip);

		// 建立请求
		String sHtmlText = AlipaySubmit.buildRequest(sParaTemp, "get", "确认");
		// System.out.println(sHtmlText);
		try {
			response.setContentType("text/html;charset=utf-8");
			PrintWriter out = response.getWriter();
			out.println(sHtmlText);
		}
		catch (IOException e) {
			e.printStackTrace();
			logger.error("组装支付宝支付参数报错", e);
		}
	}

	public TradeInfoService getTradeInfoService() {
		return tradeInfoService;
	}

	public void setTradeInfoService(TradeInfoService tradeInfoService) {
		this.tradeInfoService = tradeInfoService;
	}

	public String getResult() {
		return result;
	}

	public void setResult(String result) {
		this.result = result;
	}

	public OrderInfo getOrderInfo() {
		return orderInfo;
	}

	public void setOrderInfo(OrderInfo orderInfo) {
		this.orderInfo = orderInfo;
	}

	public OrderInfoService getOrderInfoService() {
		return orderInfoService;
	}

	public void setOrderInfoService(OrderInfoService orderInfoService) {
		this.orderInfoService = orderInfoService;
	}

	public TradeInfo getTradeInfo() {
		return tradeInfo;
	}

	public void setTradeInfo(TradeInfo tradeInfo) {
		this.tradeInfo = tradeInfo;
	}

	public String getBackMessage() {
		return backMessage;
	}

	public void setBackMessage(String backMessage) {
		this.backMessage = backMessage;
	}

	public AccountService getAccountService() {
		return accountService;
	}

	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

	public AlipayAccountService getAlipayAccountService() {
		return alipayAccountService;
	}

	public void setAlipayAccountService(
			AlipayAccountService alipayAccountService) {
		this.alipayAccountService = alipayAccountService;
	}

	public AlipayAccount getAlipayAccount() {
		return alipayAccount;
	}

	public void setAlipayAccount(AlipayAccount alipayAccount) {
		this.alipayAccount = alipayAccount;
	}

	public AccountAlipayGoodsService getAccountAlipayGoodsService() {
		return accountAlipayGoodsService;
	}

	public void setAccountAlipayGoodsService(
			AccountAlipayGoodsService accountAlipayGoodsService) {
		this.accountAlipayGoodsService = accountAlipayGoodsService;
	}

	@Override
	public void setSession(Map<String, Object> map) {
		this.session = map;
	}

	@Override
	public void setServletResponse(HttpServletResponse response) {
		this.response = response;
	}

	@Override
	public void setServletRequest(HttpServletRequest request) {
		this.request = request;
	}

}
